package wechatpay

import (
	"bytes"
	"context"
	"crypto/tls"
	"fmt"
	"log"
	"net/http"
	"time"
)

// ------------ Api v3 - payClient(支付 Http 客户端) -----------------//

type PayClient struct {
	httpClient *http.Client
}

// 初始化客户端
func NewPayClient(httpClient *http.Client) *PayClient {
	if httpClient == nil {
		httpClient = http.DefaultClient
		httpClient.Timeout = time.Second * 5
	}

	return &PayClient{
		httpClient: httpClient,
	}
}

// 初始化带证书请求的客户端
func NewTlsClient() *PayClient {
	certs, _ := tls.LoadX509KeyPair(wechatPayCert, wechatPayKey)
	client := &http.Client{
		Timeout: 10 * time.Second,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				RootCAs:      nil,
				Certificates: []tls.Certificate{certs},
			},
		},
	}
	return NewPayClient(client)
}

// 初始化带证书请求的客户端
func NewZmTlsClient() *PayClient {
	certs, _ := tls.LoadX509KeyPair(apiclientCert, apiclientKey)
	client := &http.Client{
		Timeout: 10 * time.Second,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				RootCAs:      nil,
				Certificates: []tls.Certificate{certs},
			},
		},
	}
	return NewPayClient(client)
}

// get请求
func (pc *PayClient) Get(url string, headers map[string]string) (*PayData, error) {
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return nil, err
	}

	for h, v := range headers {
		req.Header.Set(h, v)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()

	req = req.WithContext(ctx)

	httpResp, err := pc.httpClient.Do(req) // 发送HTTP请求并返回HTTP响应
	if err != nil {
		return nil, err
	}
	defer httpResp.Body.Close()

	respData := NewPayData()
	err = respData.FromJson(httpResp.Body)
	if err != nil {
		return nil, err
	}
	if httpResp.StatusCode != http.StatusOK {
		return respData, fmt.Errorf("http.Status: %s", httpResp.Status)
	}
	return respData, nil
}

// post请求
func (pc *PayClient) Post(url string, headers map[string]string, body string) (*PayData, error) {
	log.Println("POST请求", url)
	log.Println("POST请求", body)
	req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader([]byte(body)))
	if err != nil {
		return nil, err
	}

	for h, v := range headers {
		req.Header.Set(h, v)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()

	req = req.WithContext(ctx)

	httpResp, err := pc.httpClient.Do(req) // 发送HTTP请求并返回HTTP响应
	if err != nil {
		return nil, err
	}
	defer httpResp.Body.Close()

	respData := NewPayData()
	err = respData.FromJson(httpResp.Body)
	if err != nil {
		return nil, err
	}
	if httpResp.StatusCode != http.StatusOK {
		return respData, fmt.Errorf("http.Status: %s", httpResp.Status)
	}
	return respData, nil
}
